package com.tymoshenko.seabattle.shared.model.domain;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Yakiv Tymoshenko
 * @since 23.01.13
 */
public class Point implements Serializable {

    private int row;          // ensure 1 <= row <= Board.HEIGHT
    private int col;          // ensure 1 <= col <= Board.WIDTH

    @SuppressWarnings("unused")
    private Point() {
    }

    private Point(int row, int col) {
        this.row = row;
        this.col = col;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Point)) return false;

        Point point = (Point) o;

        if (col != point.col) return false;
        if (row != point.row) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = row;
        result = 31 * result + col;
        return result;
    }

    @Override
    public String toString() {
        return "(" + row + ", " + col + ")";
    }

    public int getRow() {
        return row;
    }

    public int getCol() {
        return col;
    }

    private static Map<Integer, Point> cash;

    static {
        cash = new HashMap<Integer, Point>(Board.WIDTH * Board.HEIGHT);
        cash.put(0, null);      // intended to make all points out-of-board to be null
    }

    public static Point valueOf(int row, int col) throws IllegalArgumentException {
        if (cash.containsKey(getSequenceNumber(row, col))) {
            return cash.get(getSequenceNumber(row, col));
        } else {
            Point result = new Point(row, col);
            cash.put(getSequenceNumber(row, col), result);
            return result;
        }
    }

    // TODO fix bug: fails if row or col is out of range [1..10]
    public static int getSequenceNumber(int row, int col) {
        int index = 0;  // to ensure that every out-of-board Point will be made null;
        if (row >= 1 && row <= Board.HEIGHT && col >= 1 && col <= Board.WIDTH) {
            index = row * Board.HEIGHT + col - Board.WIDTH;
        }
        return index;
    }
}
